package com.mlody.chapter22;

/**
 * Created by tmlod_000 on 2014-11-29.
 */
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JOptionPane;

/**
 * This simple word games asks the user to detect if a given letter
 * is found in the displayed word.
 * @author jdalbey
 */
public class GameFrame extends javax.swing.JFrame implements ActionListener
{
    private final static int kTurnLimit = 10;
    // Number of turns taken
    private int turnCount = 0;
    // Number of correct guesses the player has made
    private int correctGuesses = 0;
    // When the game started
    private long gameStartTime;
    // True means Yes is correct, False means No is correct
    private boolean answerFlag;

    /** Creates new form GameFrame */
    public GameFrame()
    {
        super("Word Game");
        initComponents();
        gameStartTime = System.currentTimeMillis();
        displayClue();
    }
    /* Display a random word and a letter */
    private void displayClue()
    {
        // Check if the game is over
        if (turnCount >= kTurnLimit)
        {
            gameOver();
        }
        // Get the word and clue and put them in the display
        String word = getRandomWord();
        lblWord.setText(word);
        lblLetter.setText("" + getLetterClue(word));
        turnCount++;
    }
    /* Show the end game statistics */
    private void gameOver()
    {
        // Compute elapsed time in seconds
        long elapsed = System.currentTimeMillis() - gameStartTime;
        elapsed = elapsed / 1000;
        String result = "Score: " + correctGuesses + "/" + kTurnLimit + "\n"
                + elapsed + " seconds";
        JOptionPane.showMessageDialog(this, result, "Game Over",
                JOptionPane.INFORMATION_MESSAGE);
        // Restart the game
        turnCount = 0;
        correctGuesses = 0;
        gameStartTime = System.currentTimeMillis();
    }
    /* Select a random word from the list */
    private String getRandomWord()
    {
        int randIndex = (int) (Math.random() * (wordlist.length));
        String randomWord = wordlist[randIndex];
        String mixedWord = "";
        /* Scramble the case of the letters in the word */
        for (char ltr : randomWord.toCharArray())
        {
            int choice = (int) (Math.random() * 2);
            // 50% of the time convert to upper case
            if (choice == 0)
            {
                ltr = Character.toUpperCase(ltr);
            }
            mixedWord += ltr;
        }
        return mixedWord;
    }
    /* Pick a letter to use as a clue */
    private char getLetterClue(String word)
    {
        char clue;
        final String alphabet = "abcdefghikjlmnopqrstuvwxyz";
        Set<Character> letterSet = convertStringToSet(word);
        Set<Character> alphabetSet = convertStringToSet(alphabet);
        alphabetSet.removeAll(letterSet);  // find unused letters
        int choice = (int) (Math.random() * 2);
        // 50% of the time pick a letter that is found in the word
        if (choice == 0)
        {
            // pick our clue from the letters
            int randIndex = (int) (Math.random() * (letterSet.size()));
            List<Character> uniqueLetters = new ArrayList<Character>(letterSet);
            clue = uniqueLetters.get(randIndex);
            answerFlag = true;
        }
        else
        {
            // pick our clue from the unused letters
            int randIndex = (int) (Math.random() * (alphabetSet.size()));
            List<Character> uniqueLetters =
                    new ArrayList<Character>(alphabetSet);
            clue = uniqueLetters.get(randIndex);
            answerFlag = false;
        }
        return Character.toLowerCase(clue);
    }
    /* Convert a string to a set of characters */
    private Set<Character> convertStringToSet(String word)
    {
        char[] letters = word.toCharArray();
        HashSet<Character> result = new HashSet<Character>();
        // Add each letter to the list
        for (char ch : letters)
        {
            result.add(ch);
        }
        return result;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        wordPanel = new javax.swing.JPanel();
        lblWord = new javax.swing.JLabel();
        btnPanel = new javax.swing.JPanel();
        btnYes = new javax.swing.JButton();
        lblLetter = new javax.swing.JLabel();
        btnNo = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        lblWord.setFont(new java.awt.Font("Serif", 0, 18)); // NOI18N
        lblWord.setText("word_here_");

        javax.swing.GroupLayout wordPanelLayout = new javax.swing.GroupLayout(wordPanel);
        wordPanel.setLayout(wordPanelLayout);
        wordPanelLayout.setHorizontalGroup(
                wordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(wordPanelLayout.createSequentialGroup()
                                .addGap(143, 143, 143)
                                .addComponent(lblWord)
                                .addContainerGap(149, Short.MAX_VALUE))
        );
        wordPanelLayout.setVerticalGroup(
                wordPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, wordPanelLayout.createSequentialGroup()
                                .addContainerGap(24, Short.MAX_VALUE)
                                .addComponent(lblWord)
                                .addContainerGap())
        );

        btnYes.setText("Yes");
        btnYes.addActionListener(this);

        lblLetter.setFont(new java.awt.Font("SansSerif", 1, 36)); // NOI18N
        lblLetter.setText("A");

        btnNo.setText("No");
        btnNo.addActionListener(this);

        javax.swing.GroupLayout btnPanelLayout = new javax.swing.GroupLayout(btnPanel);
        btnPanel.setLayout(btnPanelLayout);
        btnPanelLayout.setHorizontalGroup(
                btnPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(btnPanelLayout.createSequentialGroup()
                                .addGap(88, 88, 88)
                                .addComponent(btnYes)
                                .addGap(30, 30, 30)
                                .addComponent(lblLetter)
                                .addGap(37, 37, 37)
                                .addComponent(btnNo)
                                .addContainerGap(98, Short.MAX_VALUE))
        );
        btnPanelLayout.setVerticalGroup(
                btnPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(btnPanelLayout.createSequentialGroup()
                                .addGroup(btnPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addGroup(btnPanelLayout.createSequentialGroup()
                                                .addGap(19, 19, 19)
                                                .addComponent(btnYes))
                                        .addGroup(btnPanelLayout.createSequentialGroup()
                                                .addContainerGap()
                                                .addComponent(lblLetter, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE))
                                        .addGroup(btnPanelLayout.createSequentialGroup()
                                                .addGap(21, 21, 21)
                                                .addComponent(btnNo)))
                                .addContainerGap(21, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(wordPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addComponent(btnPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addContainerGap())
        );
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addComponent(wordPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(btnPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addContainerGap(79, Short.MAX_VALUE))
        );

        pack();
    }

    // Code for dispatching events from components to event handlers.

    public void actionPerformed(java.awt.event.ActionEvent evt) {
        if (evt.getSource() == btnYes) {
            GameFrame.this.btnYesActionPerformed(evt);
        }
        else if (evt.getSource() == btnNo) {
            GameFrame.this.btnNoActionPerformed(evt);
        }
    }// </editor-fold>//GEN-END:initComponents

    private void btnYesActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnYesActionPerformed
    {//GEN-HEADEREND:event_btnYesActionPerformed
        if (answerFlag)
        {
            correctGuesses++;
        }
        displayClue();
    }//GEN-LAST:event_btnYesActionPerformed

    private void btnNoActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnNoActionPerformed
    {//GEN-HEADEREND:event_btnNoActionPerformed
        if (!answerFlag)
        {
            correctGuesses++;
        }
        displayClue();
    }//GEN-LAST:event_btnNoActionPerformed
    /**
     * @param args the command line arguments
     */
    public static void main(String args[])
    {
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new GameFrame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnNo;
    private javax.swing.JPanel btnPanel;
    private javax.swing.JButton btnYes;
    private javax.swing.JLabel lblLetter;
    private javax.swing.JLabel lblWord;
    private javax.swing.JPanel wordPanel;
    // End of variables declaration//GEN-END:variables
    private final static String[] wordlist =
            {
                    "strikeouts", "releasable",
                    "luminously", "humidified", "isometrics", "guillotine", "handpicked",
                    "ligaturing", "lengthways", "lorgnettes", "remarkably", "watermelon",
                    "crocheting", "reunifying", "unravelled", "earmarking", "unbearable",
                    "chirrupped", "respectful", "represents", "pedestrian", "declension",
                    "psychopath", "meaningful", "butternuts", "fleshliest", "buttercups",
                    "supervened", "recaptured", "conciliate"
            };
}

